package cn.echogo.framework.commons;

import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 异步任务执行池
 * 
 * @version 1.0
 * @author Stan Rong 2012-9-26
 */
public class EGAsyncTaskPool {

	private static final int CORE_POOL_SIZE = 5;
	private static final int MAXIMUM_POOL_SIZE = 128;
	private static final int KEEP_ALIVE = 10;

	final BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(10);

	final ThreadFactory threadFactory = new ThreadFactory() {
		private final AtomicInteger count = new AtomicInteger(1);

		public Thread newThread(Runnable r) {
			return new Thread(r, "AsyncTask #" + count.getAndIncrement());
		}
	};

	private final ThreadPoolExecutor executor = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, workQueue, threadFactory);

	private ConcurrentHashMap<Integer, Future> futureMap = new ConcurrentHashMap<Integer, Future>();

	public EGAsyncTaskPool() {
		
	}
	
	/**
	 * 提交任务到池中
	 * @param id
	 * @param task
	 */
	public void submit(int id, Runnable task) {
		Future future = executor.submit(task);
		futureMap.put(id, future);
	}

	/**
	 * 取消并移除任务
	 * @param id
	 */
	public void cancel(int id) {
		if (futureMap.containsKey(id)) {
			Future future = futureMap.get(id);
			if (future != null) {
				future.cancel(true);
			}
			futureMap.remove(id);
		}
	}

	/**
	 * 取消所有任务
	 */
	public void cancelAll() {
		Set<Entry<Integer, Future>> entrySet = futureMap.entrySet();
		Iterator<Entry<Integer, Future>> iterator = entrySet.iterator();
		while (iterator.hasNext()) {
			Entry<Integer, Future> entry = iterator.next();
			Future future = entry.getValue();
			if (future != null) {
				future.cancel(true);
			}
		}
		futureMap.clear();
	}

}
